/**
 * Copyright 2009 cestum.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.cestum.cave.presenter.wave.cursors
{
import org.cestum.cave.ui.components.wave.Blip;
import org.cestum.cave.ui.components.wave.BlipThread;
import org.goverla.collections.ArrayList;
import org.goverla.collections.HashMap;
import org.goverla.collections.Stack;
import org.waveprotocol.wave.model.document.operation.AnnotationBoundaryMap;
import org.waveprotocol.wave.model.document.operation.Attributes;
import org.waveprotocol.wave.model.document.operation.BufferedDocOp;
import org.waveprotocol.wave.model.document.operation.DocInitializationCursor;
import org.waveprotocol.wave.model.util.StringBuilder;

public final class CaveManifestInitCursor implements DocInitializationCursor
{
	private var elemStack:Stack = new Stack();
	private var threadStack:Stack = new Stack();;
	private var currThread:BlipThread = BlipThread.createThread("root", null);
	private var docs:HashMap;
	private var currentLine:StringBuilder;
	private var lines:ArrayList;
	private var document:BufferedDocOp;
	private var createBlipFunction:Function;
	private var renderDoc:Function;
	private var lastBlip:Blip;
	//singleton?
	private static var thisInstance:CaveManifestInitCursor;
	
	function CaveManifestInitCursor() 	{}
	
	public static function of(manifest:BufferedDocOp, _docs:HashMap, createBlip:Function, renderDoc:Function):CaveManifestInitCursor {
		if (thisInstance == null)
			thisInstance = new CaveManifestInitCursor();
		thisInstance.docs = _docs;
		thisInstance.document = manifest;
		thisInstance.createBlipFunction = createBlip;
		thisInstance.renderDoc = renderDoc;
		return thisInstance;
	}
	
	public function annotationBoundary(map:AnnotationBoundaryMap):void 	{
		trace("Just for debugging...");
		//TODO need to extract the annotations
	}
	
	public function characters(chars:String):void 	{
		// ignore characters in a manifest.
		trace("chars found!");
	}
	
	public function elementStart(type:String, attrs:Attributes):void 	{
		elemStack.enqueue(type);
		if (type == caveRenderUtils.BLIP) {
			if (attrs.containsKey(caveRenderUtils.BLIP_ID)) {
				var document:BufferedDocOp = docs.getItem(attrs.getValue(caveRenderUtils.BLIP_ID)) as BufferedDocOp;
				var blipId:String = attrs.getValue(caveRenderUtils.BLIP_ID) as String;
				lastBlip = createBlipFunction.call(this, blipId, currThread);
				renderDoc.call(this, document, blipId);
			}
		} else if (type == (caveRenderUtils.THREAD)) {			
			threadStack.enqueue(currThread);
			var threadId:String = attrs.getValue(caveRenderUtils.BLIP_ID) as String;
			currThread = BlipThread.createThread(threadId, lastBlip);
			//a new thread identifies the root of Blips
		} else {
			// "Unsupported element type"
		}
	}
	
	public function elementEnd():void
	{
		var type:String = elemStack.dequeue() as  String;
		if (type == (caveRenderUtils.THREAD)) {
			currThread = threadStack.dequeue() as BlipThread;
		}
	}
	
	
}
}